#include <xsm/xsm.h>
#include <asm/p2m.h>
+int physdev_map_pirq(domid_t, int type, int *index, int *pirq_p,
+ struct msi_info *);
+int physdev_unmap_pirq(domid_t, int pirq);
+
#ifndef COMPAT
typedef long ret_t;
-#endif
static int physdev_hvm_map_pirq(
- struct domain *d, struct physdev_map_pirq *map)
+ struct domain *d, int type, int *index, int *pirq)
{
- int pirq, ret = 0;
+ int ret = 0;
spin_lock(&d->event_lock);
- switch ( map->type )
+ switch ( type )
{
case MAP_PIRQ_TYPE_GSI: {
struct hvm_irq_dpci *hvm_irq_dpci;
if ( hvm_irq_dpci )
{
list_for_each_entry ( girq,
- &hvm_irq_dpci->girq[map->index],
+ &hvm_irq_dpci->girq[*index],
list )
machine_gsi = girq->machine_gsi;
}
/* found one, this mean we are dealing with a pt device */
if ( machine_gsi )
{
- map->index = domain_pirq_to_irq(d, machine_gsi);
- pirq = machine_gsi;
- ret = (pirq > 0) ? 0 : pirq;
+ *index = domain_pirq_to_irq(d, machine_gsi);
+ *pirq = machine_gsi;
+ ret = (*pirq > 0) ? 0 : *pirq;
}
/* we didn't find any, this means we are dealing
* with an emulated device */
else
{
- pirq = map->pirq;
- if ( pirq < 0 )
- pirq = get_free_pirq(d, map->type, map->index);
- ret = map_domain_emuirq_pirq(d, pirq, map->index);
+ if ( *pirq < 0 )
+ *pirq = get_free_pirq(d, type, *index);
+ ret = map_domain_emuirq_pirq(d, *pirq, *index);
}
- map->pirq = pirq;
break;
}
default:
ret = -EINVAL;
- dprintk(XENLOG_G_WARNING, "map type %d not supported yet\n", map->type);
+ dprintk(XENLOG_G_WARNING, "map type %d not supported yet\n", type);
break;
}
return ret;
}
-static int physdev_map_pirq(struct physdev_map_pirq *map)
+int physdev_map_pirq(domid_t domid, int type, int *index, int *pirq_p,
+ struct msi_info *msi)
{
struct domain *d;
int pirq, irq, ret = 0;
- struct msi_info _msi;
void *map_data = NULL;
- ret = rcu_lock_target_domain_by_id(map->domid, &d);
+ ret = rcu_lock_target_domain_by_id(domid, &d);
if ( ret )
return ret;
- if ( map->domid == DOMID_SELF && is_hvm_domain(d) )
+ if ( domid == DOMID_SELF && is_hvm_domain(d) )
{
- ret = physdev_hvm_map_pirq(d, map);
+ ret = physdev_hvm_map_pirq(d, type, index, pirq_p);
goto free_domain;
}
}
/* Verify or get irq. */
- switch ( map->type )
+ switch ( type )
{
case MAP_PIRQ_TYPE_GSI:
- if ( map->index < 0 || map->index >= nr_irqs_gsi )
+ if ( *index < 0 || *index >= nr_irqs_gsi )
{
dprintk(XENLOG_G_ERR, "dom%d: map invalid irq %d\n",
- d->domain_id, map->index);
+ d->domain_id, *index);
ret = -EINVAL;
goto free_domain;
}
- irq = domain_pirq_to_irq(current->domain, map->index);
+ irq = domain_pirq_to_irq(current->domain, *index);
if ( irq <= 0 )
{
if ( IS_PRIV(current->domain) )
- irq = map->index;
+ irq = *index;
else {
dprintk(XENLOG_G_ERR, "dom%d: map pirq with incorrect irq!\n",
d->domain_id);
break;
case MAP_PIRQ_TYPE_MSI:
- irq = map->index;
+ irq = *index;
if ( irq == -1 )
irq = create_irq();
goto free_domain;
}
- _msi.bus = map->bus;
- _msi.devfn = map->devfn;
- _msi.entry_nr = map->entry_nr;
- _msi.table_base = map->table_base;
- _msi.irq = irq;
- map_data = &_msi;
+ msi->irq = irq;
+ map_data = msi;
break;
default:
dprintk(XENLOG_G_ERR, "dom%d: wrong map_pirq type %x\n",
- d->domain_id, map->type);
+ d->domain_id, type);
ret = -EINVAL;
goto free_domain;
}
/* Verify or get pirq. */
spin_lock(&d->event_lock);
pirq = domain_irq_to_pirq(d, irq);
- if ( map->pirq < 0 )
+ if ( *pirq_p < 0 )
{
if ( pirq )
{
dprintk(XENLOG_G_ERR, "dom%d: %d:%d already mapped to %d\n",
- d->domain_id, map->index, map->pirq,
- pirq);
+ d->domain_id, *index, *pirq_p, pirq);
if ( pirq < 0 )
{
ret = -EBUSY;
}
else
{
- pirq = get_free_pirq(d, map->type, map->index);
+ pirq = get_free_pirq(d, type, *index);
if ( pirq < 0 )
{
dprintk(XENLOG_G_ERR, "dom%d: no free pirq\n", d->domain_id);
}
else
{
- if ( pirq && pirq != map->pirq )
+ if ( pirq && pirq != *pirq_p )
{
dprintk(XENLOG_G_ERR, "dom%d: pirq %d conflicts with irq %d\n",
- d->domain_id, map->index, map->pirq);
+ d->domain_id, *index, *pirq_p);
ret = -EEXIST;
goto done;
}
else
- pirq = map->pirq;
+ pirq = *pirq_p;
}
- ret = map_domain_pirq(d, pirq, irq, map->type, map_data);
+ ret = map_domain_pirq(d, pirq, irq, type, map_data);
if ( ret == 0 )
- map->pirq = pirq;
+ *pirq_p = pirq;
if ( !ret && is_hvm_domain(d) )
map_domain_emuirq_pirq(d, pirq, IRQ_PT);
done:
spin_unlock(&d->event_lock);
spin_unlock(&pcidevs_lock);
- if ( (ret != 0) && (map->type == MAP_PIRQ_TYPE_MSI) && (map->index == -1) )
+ if ( (ret != 0) && (type == MAP_PIRQ_TYPE_MSI) && (*index == -1) )
destroy_irq(irq);
free_domain:
rcu_unlock_domain(d);
return ret;
}
-static int physdev_unmap_pirq(struct physdev_unmap_pirq *unmap)
+int physdev_unmap_pirq(domid_t domid, int pirq)
{
struct domain *d;
int ret;
- ret = rcu_lock_target_domain_by_id(unmap->domid, &d);
+ ret = rcu_lock_target_domain_by_id(domid, &d);
if ( ret )
return ret;
if ( is_hvm_domain(d) )
{
spin_lock(&d->event_lock);
- ret = unmap_domain_pirq_emuirq(d, unmap->pirq);
+ ret = unmap_domain_pirq_emuirq(d, pirq);
spin_unlock(&d->event_lock);
- if ( unmap->domid == DOMID_SELF || ret )
+ if ( domid == DOMID_SELF || ret )
goto free_domain;
}
spin_lock(&pcidevs_lock);
spin_lock(&d->event_lock);
- ret = unmap_domain_pirq(d, unmap->pirq);
+ ret = unmap_domain_pirq(d, pirq);
spin_unlock(&d->event_lock);
spin_unlock(&pcidevs_lock);
rcu_unlock_domain(d);
return ret;
}
+#endif /* COMPAT */
ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
{
}
case PHYSDEVOP_map_pirq: {
- struct physdev_map_pirq map;
+ physdev_map_pirq_t map;
+ struct msi_info msi;
ret = -EFAULT;
if ( copy_from_guest(&map, arg, 1) != 0 )
break;
- ret = physdev_map_pirq(&map);
+ msi.bus = map.bus;
+ msi.devfn = map.devfn;
+ msi.entry_nr = map.entry_nr;
+ msi.table_base = map.table_base;
+ ret = physdev_map_pirq(map.domid, map.type, &map.index, &map.pirq,
+ &msi);
if ( copy_to_guest(arg, &map, 1) != 0 )
ret = -EFAULT;
if ( copy_from_guest(&unmap, arg, 1) != 0 )
break;
- ret = physdev_unmap_pirq(&unmap);
+ ret = physdev_unmap_pirq(unmap.domid, unmap.pirq);
break;
}
#define physdev_apic compat_physdev_apic
#define physdev_apic_t physdev_apic_compat_t
-#define physdev_eoi compat_physdev_eoi
-#define physdev_eoi_t physdev_eoi_compat_t
+#define xen_physdev_eoi physdev_eoi
+CHECK_physdev_eoi;
+#undef xen_physdev_eoi
#define physdev_pirq_eoi_gmfn compat_physdev_pirq_eoi_gmfn
#define physdev_pirq_eoi_gmfn_t physdev_pirq_eoi_gmfn_compat_t
#define physdev_set_iobitmap compat_physdev_set_iobitmap
#define physdev_set_iobitmap_t physdev_set_iobitmap_compat_t
-#define physdev_set_iopl compat_physdev_set_iopl
-#define physdev_set_iopl_t physdev_set_iopl_compat_t
+#define xen_physdev_set_iopl physdev_set_iopl
+CHECK_physdev_set_iopl;
+#undef xen_physdev_set_iopl
-#define physdev_irq compat_physdev_irq
-#define physdev_irq_t physdev_irq_compat_t
+#define xen_physdev_irq physdev_irq
+CHECK_physdev_irq;
+#undef xen_physdev_irq
-#define physdev_irq_status_query compat_physdev_irq_status_query
-#define physdev_irq_status_query_t physdev_irq_status_query_compat_t
+#define xen_physdev_irq_status_query physdev_irq_status_query
+CHECK_physdev_irq_status_query;
+#undef xen_physdev_irq_status_query
-#define physdev_map_pirq compat_physdev_map_pirq
#define physdev_map_pirq_t physdev_map_pirq_compat_t
-#define physdev_unmap_pirq compat_physdev_unmap_pirq
-#define physdev_unmap_pirq_t physdev_unmap_pirq_compat_t
+#define xen_physdev_unmap_pirq physdev_unmap_pirq
+CHECK_physdev_unmap_pirq;
+#undef xen_physdev_unmap_pirq
-#define physdev_manage_pci compat_physdev_manage_pci
-#define physdev_manage_pci_t physdev_manage_pci_compat_t
+#define xen_physdev_manage_pci physdev_manage_pci
+CHECK_physdev_manage_pci;
+#undef xen_physdev_manage_pci
-#define physdev_manage_pci_ext compat_physdev_manage_pci_ext
-#define physdev_manage_pci_ext_t physdev_manage_pci_ext_compat_t
+#define xen_physdev_manage_pci_ext physdev_manage_pci_ext
+CHECK_physdev_manage_pci_ext;
+#undef xen_physdev_manage_pci_ext
-#define physdev_restore_msi compat_physdev_restore_msi
-#define physdev_restore_msi_t physdev_restore_msi_compat_t
+#define xen_physdev_restore_msi physdev_restore_msi
+CHECK_physdev_restore_msi;
+#undef xen_physdev_restore_msi
-#define physdev_setup_gsi compat_physdev_setup_gsi
-#define physdev_setup_gsi_t physdev_setup_gsi_compat_t
+#define xen_physdev_setup_gsi physdev_setup_gsi
+CHECK_physdev_setup_gsi;
+#undef xen_physdev_setup_gsi
-#define physdev_get_free_pirq compat_physdev_get_free_pirq
-#define physdev_get_free_pirq_t physdev_get_free_pirq_compat_t
+#define xen_physdev_get_free_pirq physdev_get_free_pirq
+CHECK_physdev_get_free_pirq;
+#undef xen_physdev_get_free_pirq
#define COMPAT
#undef guest_handle_okay